#include "multi_view_combobox.h"
#include <QCheckBox>
#include <QStylePainter>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include <QAbstractItemView>
#include <QDebug>
ComboBoxItemDelegate::ComboBoxItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{

}

QWidget* ComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	return QStyledItemDelegate::createEditor(parent, option, index);
}

void ComboBoxItemDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
{
	if (option->state.testFlag(QStyle::State_HasFocus))
	{
		option->backgroundBrush = m_backColor.value<QColor>();
	}
}

QSize ComboBoxItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	return QStyledItemDelegate::sizeHint(option, index);
}

void ComboBoxItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QStyleOptionViewItem viewOption(option);
	initStyleOption(&viewOption, index);
	if (option.state.testFlag(QStyle::State_HasFocus))
	{
		viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
	}

	QStyledItemDelegate::paint(painter, option, index);

	QStyleOptionButton btnOption;
	btnOption.rect = option.rect;
	btnOption.rect.setLeft(option.rect.left() + 13);
	btnOption.rect.setTop(option.rect.top() + (option.rect.height() - 16) / 2);
	btnOption.rect.setWidth(16);
	btnOption.rect.setHeight(16);

	auto checked = index.data(Qt::UserRole + 1).toBool();

	btnOption.state = checked ? QStyle::State_On : QStyle::State_Off;
	btnOption.state |= QStyle::State_Enabled;

	QCheckBox btn;
	btn.setCheckable(true);
	btn.setChecked(checked);

	QApplication::style()->unpolish(&btn);
	QApplication::style()->polish(&btn);
	QApplication::style()->drawControl(QStyle::CE_CheckBox, &btnOption, painter, &btn);

	QFont font;
	font.setPixelSize(16);
	QFontMetrics metrics(font);
	painter->setPen(QPen("#7DDBFF"));
	painter->setFont(font);

	painter->drawText(QPoint(option.rect.left() + 40, option.rect.top() + option.rect.height() / 2 + 4), index.data(Qt::DisplayRole).toString());

}

bool ComboBoxItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
	if (event->type() == QEvent::MouseButtonDblClick)
	{
		return true;
	}
	if (event->type() == QEvent::MouseButtonRelease)
	{
		return false;
	}

	if (event->type() == QEvent::MouseButtonPress)
	{
		emit signal_btn_clicked(index);
	}

	return QStyledItemDelegate::editorEvent(event, model, option, index);
}

void ComboBoxItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
	editor->setGeometry(option.rect);
}

MultiViewComboBox::MultiViewComboBox(QWidget* parent) : QComboBox(parent)
{
    auto delegate = new ComboBoxItemDelegate(this);
	setItemDelegate(delegate);

    connect(delegate, &ComboBoxItemDelegate::signal_btn_clicked, this, [this](const QModelIndex& index)
	{
		auto checked = !index.data(Qt::UserRole + 1).toBool();
		this->model()->setData(index, checked, Qt::UserRole + 1);

		QStringList texts = m_text.isEmpty() ? QStringList() : m_text.split(";");
		if (checked)
		{
			texts.append(index.data().toString());
		}
		else
		{
			texts.removeOne(index.data().toString());
		}
		m_text = texts.join(";");
	});
}

void MultiViewComboBox::setData(const QVariant& data)
{
	QStringList texts;
	auto datas = data.toList();
	for (int index = 0; index < count(); ++index)
	{
		auto mIndex = model()->index(index, 0);
		if (datas.contains(mIndex.data(Qt::UserRole)))
		{
			model()->setData(mIndex, true, Qt::UserRole + 1);
			model()->setData(mIndex, true, Qt::UserRole + 2);
			texts.append(mIndex.data().toString());
		}
	}

	m_text = texts.join(";");
}

QVariant MultiViewComboBox::data() const
{
	QVariantList datas;
	for (int index = 0; index < count(); ++index)
	{
		auto mIndex = model()->index(index, 0);
		if (mIndex.data(Qt::UserRole + 1).toBool())
		{
			datas.append(mIndex.data(Qt::UserRole));
		}
	}
	return datas;
}

void MultiViewComboBox::hidePopup()
{
    QWidget *popup = this->findChild<QFrame*>();
    if(!popup->geometry().contains(QCursor::pos()))
    {
        QComboBox::hidePopup();
    }
}

void MultiViewComboBox::paintEvent(QPaintEvent* e)
{
	QStylePainter painter(this);
	painter.setPen(palette().color(QPalette::Text));

	QStyleOptionComboBox opt;
	initStyleOption(&opt);
	painter.drawComplexControl(QStyle::CC_ComboBox, opt);

	if (opt.editable)
	{
		painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
		return;
	}

	QRect editRect = this->style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);

	QStyleOptionButton buttonOpt;
	buttonOpt.initFrom(this);
	buttonOpt.direction = Qt::LeftToRight;
	buttonOpt.rect = editRect;
	buttonOpt.text = m_text;
	buttonOpt.icon = opt.currentIcon;
	buttonOpt.iconSize = opt.iconSize;

	painter.drawControl(QStyle::CE_CheckBoxLabel, buttonOpt);
}
